iT邦幫忙

2022 iThome 鐵人賽

DAY 16
1

JOIN是SQL當中扮演非常重要的角色,它的功能就是拿來將不同資料表進行關聯。
Day 15 我們知道為什麼要正規化、Day 16 了解關於Key的作用,所以今天使用JOIN之前,先來建立已經正規化且設置PERMARY KEY的資料表,不過FOREIGN KEY會稍後再加入,先宣告成INT NOT NULL就好。

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(300) NOT NULL,
    email VARCHAR(300) NOT NULL,
    address_id INT NOT NULL -- 稍後補上FOREIGN KEY正式語法
);

CREATE TABLE addresses (
    id SERIAL PRIMARY KEY,
    address VARCHAR(300) NOT NULL,
    district_id INT NOT NULL -- 稍後補上FOREIGN KEY正式語法
);

CREATE TABLE districts (
    id SERIAL PRIMARY KEY,
    name VARCHAR(300) UNIQUE NOT NULL
);

接著我們來插入一些資料,因為users資料表的address_id欄位需要addresses資料表的id,而addresses資料表的district_id欄位需要districts資料表的id欄位,寫入資料必需先寫districts,再寫addresses再寫users。

INSERT INTO districts (name)
VALUES ('雲林縣'),('嘉義縣'),('台南市'),('高雄市');

INSERT INTO addresses (address, district_id)
VALUES 
    ('雲林縣斗南鎮賢者模式路0號', 1),
    ('嘉義縣民雄鄉肉包路35號',2),
    ('台南市歸仁區沙城路980號',3),
		('高雄市旗津區砲台路168號',4);
		

INSERT INTO users (name, email, address_id)
VALUES 
    ('鄭小元', 'smallbaby@gmail.com', 1),
    ('李小刀', 'okok148@gmail.com',2),
    ('詹小舜', 'lbjking2003@gmail.com',3);

INNER JOIN

  1. (SELECT) 找出欄位的值,*代表全部的欄位
  2. (FROM) 從哪張表格找
  3. (JOIN) 而且還要跟哪張表格連接
  4. (INNER) 兩張表格都對應的起來的才顯示
  5. (ON) 連接的表格各自要用哪一個欄位去對應,通常是FROM那個資料表的Foreign Key對應到INNER JOIN的Primary Key。
SELECT *
FROM users 
INNER JOIN addresses ON users.address_id = addresses.id;

不一定要明確標示資料表

我們不一定要在ON明確標示出資料表(table)名稱,只要這串SQL所執行的欄位可以清楚識別是屬於哪一個資料表的時候,你是可以省略的,例如address_id只有users資料表有,addresses則沒有,那麼就可以只寫address_id就好,資料庫自己會知道是個資料表,不過再看到id則是兩個資料表都有,你是不能省略的,一定要標示出你是要用哪一個id,所以此例要寫出addresses.id。

SELECT *
FROM users 
INNER JOIN addresses ON address_id = addresses.id;

可以使用AS替換資料表名稱

通常使用AS來替換資料表名稱的目的是為了縮短資料表名稱,例如users替換成u,addresses替換成a,這不是必要的作法,但是如果你開始認為SQL指令長到看起來有點吃力的時候,那麼就可以試試使用AS來命名。

SELECT a.id, name, email, address
FROM users AS u
INNER JOIN addresses AS a ON u.address_id = a.id;

另外替換名稱其實也可以省略AS,甚至有些資料庫只接受這種寫法,不過我自己是喜歡加上AS,對我而言感覺更為明確。

SELECT u.id, name, email, address
FROM users u
INNER JOIN addresses a ON u.address_id = a.id;

Multiple JOINs

JOIN在很多專案中不會只有JOIN一次而已,會依據當初拆分的表格數或要取出來的資料範圍來看要JOIN幾張資料表,在這個例子只有三張資料表,我們可以JOIN之後再JOIN,用法是一樣的,如下例所示,要稍微注意一下SELECT的內容在name有衝突,因此要標記是哪個資料表的name,然後d.name在輸出欄位的時候感覺不夠明確,因此使用AS命名為district,如此一來就能依據這個指令組出資料的全貌。

SELECT u.id, u.name, email, d.name AS district, address
FROM users AS u
INNER JOIN addresses AS a ON u.address_id = a.id
INNER JOIN districts AS d ON a.district_id = d.id;

LEFT JOIN

  1. (SELECT) 找出欄位的值,*代表全部的欄位
  2. (FROM) 從哪張表格找
  3. (JOIN) 而且還要跟哪張表格連接
  4. (LEFT) JOIN關係當中左邊那個表格有的就要顯示
  5. (ON) 連接的表格各自要用哪一個欄位去對應,通常是FROM那個資料表的Foreign Key對應到INNER JOIN的Primary Key。
SELECT u.id, name, email, address
FROM users AS u
LEFT JOIN addresses AS a ON u.address_id = a.id;

你會發現跟INNER JOIN找出來的資料是一樣的,不過如果我們JOIN的角度改變,我們改用從addresses表格去找,而且還要跟users連接,JOIN關係的左邊變成了addresses,也就是addresses表格中有的資料就要顯示出來,例如高雄市旗津區砲台路168號找不到對應的人,顯示出來的user就會是NULL。

SELECT u.id, name, email, address
FROM addresses AS a
LEFT JOIN users AS u ON a.id = u.address_id;

RIGHT JOIN

  1. (SELECT) 找出欄位的值,*代表全部的欄位
  2. (FROM) 從哪張表格找
  3. (JOIN) 而且還要跟哪張表格連接
  4. (RIGHT) JOIN關係當中右邊那個表格有的就要顯示
  5. (ON) 連接的表格各自要用哪一個欄位去對應,通常是FROM那個資料表的Foreign Key對應到INNER JOIN的Primary Key。

RIGHT JOIN 的觀念同LEFT JOIN,只是要全抓的資料從左邊那張變成右邊那張,不過不見得需要用到RIGHT JOIN,因為可以透過JOIN資料表位置對調就能用LEFT JOIN找出一樣的內容。

SELECT u.id, name, email, address
FROM users AS u
RIGHT JOIN addresses AS a ON u.address_id = a.id;

CROSS JOIN

笛卡爾乘積運算,通俗一點的說法是把表格所有的配對可能都給列出來,例如幫男女進行配對。

CREATE TABLE boys (
    name VARCHAR(300)
);

CREATE TABLE grils (
    name VARCHAR(300)
);

INSERT INTO boys (name)
VALUES ('王小明'),('蘇大聰'),('陳小龍');

INSERT INTO grils (name)
VALUES ('林小美'),('吳大妞'),('張小柯');

算出每個組合的速配率,是不是很好玩XD

SELECT  b.name AS 男方, g.name AS 女方, FLOOR(RANDOM()*100+1) AS 速配率
FROM boys AS b
CROSS JOIN grils AS g;

UNION

UNION是另一種可以把資料表資料合併起來的方式,不過觀念跟JOIN差很多,事實上UNION比JOIN簡單很多,它必需是資料表的欄位數量跟順序都一樣,可以看成是相同資料的合併,例如我們可以靠這個方列出所有參加配對遊戲的人,不分男女老少,UNION的使用情境會比JOIN少很多,因為要找到相同型態跟欄位又分開放不太容易,通常是偏向特定資料管理面的因素居多。

SELECT  * FROM boys
UNION
SELECT * FROM grils;

上一篇
Day 16 初探Key
下一篇
Day 18 外鍵限制
系列文
資料庫新手入門--以PostgreSQL為例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
W.H.
iT邦新手 1 級 ‧ 2022-09-19 12:37:17

我來啦~/images/emoticon/emoticon35.gif給你按個讚!!

啾啾丸 iT邦新手 2 級 ‧ 2022-09-20 06:58:55 檢舉

哈哈哈,你人真好耶!

0

推推!

啾啾丸 iT邦新手 2 級 ‧ 2022-09-20 07:00:52 檢舉

感謝支持,不過因為按錯發文的地方,這個系列不小心斷賽了,之後會不定期的更新。

我要留言

立即登入留言